// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

#include "Import/BDFImport/BulkData/Property/PCOMPGParser.h"

#include "gtest/gtest.h"

#include "Utility/Exception/SGException.h"

#include "DataStructure/Common/Constant.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Property/IPCOMPGService.h"

#include "Import/BDFImport/BDFParserBase.h"

using SG::DataStructure::Common::TOLERANCE;
using namespace SG::DataStructure::FEM;
using namespace SG::DBManager;
using namespace SG::Import;
extern std::shared_ptr<DBServiceFactory> DB_SERVICEFACTORY;
extern std::vector<std::string>          dividedEntryInfo;

class PCOMPGParserTest : public ::testing::Test
{
  public:
    static void SetUpTestSuite ()
    {
        DB_SERVICEFACTORY->ClearDatabase ();
    }
};

TEST_F (PCOMPGParserTest, Simple4Plies)
{
    std::vector<std::string> Entry = { "PCOMPG   20              ",
                                       "         1       2      0.005    0.      YES",
                                       "         2       2      0.005    0.      YES",
                                       "         3       2      0.005    0.      YES",
                                       "         4       2      0.005    0.      YES" };
    BDF::divideBulkEntry (Entry, dividedEntryInfo);
    SG::Import::BDF::BULKDATA::ParsePCOMPG (DB_SERVICEFACTORY, dividedEntryInfo);
    SG::DataStructure::FEM::PCOMPGData data;

    ASSERT_TRUE (DB_SERVICEFACTORY->get<IPCOMPGService> ()->FindById (20, data) == SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (data.m_id, 20);
    ASSERT_EQ (data.m_PLYList.size (), 4);

    for (size_t i = 0; i < 4; ++i)
    {
        ASSERT_EQ (data.m_PLYList[i].m_GPLYID, i + 1);
        ASSERT_EQ (data.m_PLYList[i].m_MID, 2);
        ASSERT_NEAR (data.m_PLYList[i].m_THICK, 0.005, TOLERANCE);
        ASSERT_NEAR (data.m_PLYList[i].m_THETA, 0.0, TOLERANCE);
        ASSERT_EQ (data.m_PLYList[i].m_SOUT, 1);
    }
}

// 东哥提供模型
TEST_F (PCOMPGParserTest, 5Plies)
{
    std::vector<std::string> Entry = { "PCOMPG       102                                                        ",
                                       "               5     120     1.0     0.0     YES",
                                       "               3     120     1.2    45.0     YES",
                                       "               2     120     1.1    60.0     YES",
                                       "               4     120    1.33    90.0     YES",
                                       "               1     120    1.47     0.0     YES" };
    BDF::divideBulkEntry (Entry, dividedEntryInfo);
    SG::Import::BDF::BULKDATA::ParsePCOMPG (DB_SERVICEFACTORY, dividedEntryInfo);
    SG::DataStructure::FEM::PCOMPGData data;

    ASSERT_TRUE (DB_SERVICEFACTORY->get<IPCOMPGService> ()->FindById (102, data) == SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (data.m_id, 102);
    ASSERT_EQ (data.m_PLYList.size (), 5);

    ASSERT_EQ (data.m_PLYList[0].m_GPLYID, 5);
    ASSERT_EQ (data.m_PLYList[0].m_MID, 120);
    ASSERT_NEAR (data.m_PLYList[0].m_THICK, 1.0, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[0].m_THETA, 0.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[0].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[1].m_GPLYID, 3);
    ASSERT_EQ (data.m_PLYList[1].m_MID, 120);
    ASSERT_NEAR (data.m_PLYList[1].m_THICK, 1.2, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[1].m_THETA, 45.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[1].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[2].m_GPLYID, 2);
    ASSERT_EQ (data.m_PLYList[2].m_MID, 120);
    ASSERT_NEAR (data.m_PLYList[2].m_THICK, 1.1, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[2].m_THETA, 60.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[2].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[3].m_GPLYID, 4);
    ASSERT_EQ (data.m_PLYList[3].m_MID, 120);
    ASSERT_NEAR (data.m_PLYList[3].m_THICK, 1.33, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[3].m_THETA, 90.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[3].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[4].m_GPLYID, 1);
    ASSERT_EQ (data.m_PLYList[4].m_MID, 120);
    ASSERT_NEAR (data.m_PLYList[4].m_THICK, 1.47, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[4].m_THETA, 0.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[4].m_SOUT, 1);
}

TEST_F (PCOMPGParserTest, CardFormatWithStar)
{
    std::vector<std::string> Entry = { "PCOMPG*                1 -5.00000000E-03",
                                       "*",
                                       "*                      5               1  2.00000000E-03  0.00000000E+00",
                                       "*         YES",
                                       "*                      4               1  2.00000000E-03  4.50000000E+01",
                                       "*         YES",
                                       "*                      3               1  2.00000000E-03  9.00000000E+01",
                                       "*         YES",
                                       "*                      2               1  2.00000000E-03 -4.50000000E+01",
                                       "*         YES",
                                       "*                      1               1  2.00000000E-03  0.00000000E+00",
                                       "*         YES" };
    BDF::divideBulkEntry (Entry, dividedEntryInfo);
    SG::Import::BDF::BULKDATA::ParsePCOMPG (DB_SERVICEFACTORY, dividedEntryInfo);
    SG::DataStructure::FEM::PCOMPGData data;

    ASSERT_TRUE (DB_SERVICEFACTORY->get<IPCOMPGService> ()->FindById (1, data) == SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (data.m_id, 1);
    ASSERT_NEAR (data.m_Z0, -5.0e-3, TOLERANCE);
    ASSERT_EQ (data.m_PLYList.size (), 5);

    ASSERT_EQ (data.m_PLYList[0].m_GPLYID, 5);
    ASSERT_EQ (data.m_PLYList[0].m_MID, 1);
    ASSERT_NEAR (data.m_PLYList[0].m_THICK, 2.0e-3, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[0].m_THETA, 0.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[0].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[1].m_GPLYID, 4);
    ASSERT_EQ (data.m_PLYList[1].m_MID, 1);
    ASSERT_NEAR (data.m_PLYList[1].m_THICK, 2.0e-3, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[1].m_THETA, 45.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[1].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[2].m_GPLYID, 3);
    ASSERT_EQ (data.m_PLYList[2].m_MID, 1);
    ASSERT_NEAR (data.m_PLYList[2].m_THICK, 2.0e-3, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[2].m_THETA, 90.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[2].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[3].m_GPLYID, 2);
    ASSERT_EQ (data.m_PLYList[3].m_MID, 1);
    ASSERT_NEAR (data.m_PLYList[3].m_THICK, 2.0e-3, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[3].m_THETA, -45.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[3].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[4].m_GPLYID, 1);
    ASSERT_EQ (data.m_PLYList[4].m_MID, 1);
    ASSERT_NEAR (data.m_PLYList[4].m_THICK, 2.0e-3, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[4].m_THETA, 0.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[4].m_SOUT, 1);
}
TEST_F (PCOMPGParserTest, MultiPly_Tsai)
{
    DB_SERVICEFACTORY->ClearDatabase ();
    std::vector<std::string> Entry = { "PCOMPG  20      -10.375         50.     TSAI    20.     0.      ",
                                       "        1022    4       1.      0.      YES     ",
                                       "        1041    5       1.25    0.      YES     ",
                                       "        1042    7       5.      0.      YES     ",
                                       "        1043    8       10.     0.      YES     ",
                                       "        1044    6       2.5     0.      YES     ",
                                       "        1059    4       1.      0.      YES     " };
    BDF::divideBulkEntry (Entry, dividedEntryInfo);
    SG::Import::BDF::BULKDATA::ParsePCOMPG (DB_SERVICEFACTORY, dividedEntryInfo);
    SG::DataStructure::FEM::PCOMPGData data;

    ASSERT_TRUE (DB_SERVICEFACTORY->get<IPCOMPGService> ()->FindById (20, data) == SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (data.m_id, 20);
    ASSERT_NEAR (data.m_Z0, -10.375, TOLERANCE);
    ASSERT_NEAR (data.m_SB, 50.0, TOLERANCE);
    ASSERT_EQ (data.m_FT, 3);  // TSAI
    ASSERT_NEAR (data.m_TREF, 20.0, TOLERANCE);
    ASSERT_NEAR (data.m_GE, 0.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList.size (), 6);

    ASSERT_EQ (data.m_PLYList[0].m_GPLYID, 1022);
    ASSERT_EQ (data.m_PLYList[0].m_MID, 4);
    ASSERT_NEAR (data.m_PLYList[0].m_THICK, 1.0, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[0].m_THETA, 0.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[0].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[1].m_GPLYID, 1041);
    ASSERT_EQ (data.m_PLYList[1].m_MID, 5);
    ASSERT_NEAR (data.m_PLYList[1].m_THICK, 1.25, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[1].m_THETA, 0.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[1].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[2].m_GPLYID, 1042);
    ASSERT_EQ (data.m_PLYList[2].m_MID, 7);
    ASSERT_NEAR (data.m_PLYList[2].m_THICK, 5.0, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[2].m_THETA, 0.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[2].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[3].m_GPLYID, 1043);
    ASSERT_EQ (data.m_PLYList[3].m_MID, 8);
    ASSERT_NEAR (data.m_PLYList[3].m_THICK, 10.0, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[3].m_THETA, 0.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[3].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[4].m_GPLYID, 1044);
    ASSERT_EQ (data.m_PLYList[4].m_MID, 6);
    ASSERT_NEAR (data.m_PLYList[4].m_THICK, 2.5, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[4].m_THETA, 0.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[4].m_SOUT, 1);

    ASSERT_EQ (data.m_PLYList[5].m_GPLYID, 1059);
    ASSERT_EQ (data.m_PLYList[5].m_MID, 4);
    ASSERT_NEAR (data.m_PLYList[5].m_THICK, 1.0, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[5].m_THETA, 0.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[5].m_SOUT, 1);
}

TEST_F (PCOMPGParserTest, GEFLG)
{
    std::vector<std::string> Entry = { "PCOMPG   2144500   -2.25                             0.0     0.0        +       ",
                                       "+            200 2100006   0.125    -45.     YES      -1                +       ",
                                       "+            201 2100006   0.125     90.     YES                        +       ",
                                       "+            202 2100006   0.125     45.     YES                        +       ",
                                       "+            203 2100006   0.125     90.     YES                        +       ",
                                       "+            204 2100006   0.125    -45.     YES                        +       ",
                                       "+            205 2100006   0.125     0.0     YES                        +       ",
                                       "+            206 2100006   0.125     45.     YES                        +       ",
                                       "+            207 2100006   0.125     0.0     YES                        +       ",
                                       "+            208 2100006   0.125    -45.     YES                        +       ",
                                       "+            209 2100006   0.125     45.     YES                        +       ",
                                       "+            210 2100006   0.125     0.0     YES                        +       ",
                                       "+            211 2100006   0.125     0.0     YES                        +       ",
                                       "+            212 2100006   0.125     45.     YES                        +       ",
                                       "+            213 2100006   0.125     0.0     YES                        +       ",
                                       "+            214 2100006   0.125     0.0     YES                        +       ",
                                       "+            215 2100006   0.125    -45.     YES                        +       ",
                                       "+            216 2100006   0.125     0.0     YES                        +       ",
                                       "+            217 2100006   0.125     90.     YES                        +       ",
                                       "+            218 2100006   0.125     90.     YES                        +       ",
                                       "+            219 2100006   0.125     0.0     YES                        +       ",
                                       "+            220 2100006   0.125    -45.     YES                        +       ",
                                       "+            221 2100006   0.125     0.0     YES                        +       ",
                                       "+            222 2100006   0.125     0.0     YES                        +       ",
                                       "+            223 2100006   0.125     45.     YES                        +       ",
                                       "+            224 2100006   0.125     0.0     YES                        +       ",
                                       "+            225 2100006   0.125     0.0     YES                        +       ",
                                       "+            230 2100006   0.125    -45.     YES                        +       ",
                                       "+            231 2100006   0.125     45.     YES                        +       ",
                                       "+            232 2100006   0.125     0.0     YES                        +       ",
                                       "+            233 2100006   0.125    -45.     YES                        +       ",
                                       "+            234 2100006   0.125     0.0     YES                        +       ",
                                       "+            235 2100006   0.125     45.     YES                        +       ",
                                       "+            236 2100006   0.125     90.     YES                        +       ",
                                       "+            237 2100006   0.125    -45.     YES                        +       ",
                                       "+            238 2100006   0.125     90.     YES                        +       ",
                                       "+            239 2100006   0.125     45.     YES                        PCOMPG_2" };
    BDF::divideBulkEntry (Entry, dividedEntryInfo);
    SG::Import::BDF::BULKDATA::ParsePCOMPG (DB_SERVICEFACTORY, dividedEntryInfo);
    SG::DataStructure::FEM::PCOMPGData data;

    ASSERT_TRUE (DB_SERVICEFACTORY->get<IPCOMPGService> ()->FindById (2144500, data) == SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (data.m_id, 2144500);
    ASSERT_NEAR (data.m_Z0, -2.25, TOLERANCE);
    ASSERT_NEAR (data.m_GE, 0.0, TOLERANCE);  // 第8字段
    ASSERT_NEAR (data.m_SB, 0.0, TOLERANCE);  // 第4字段
    ASSERT_EQ (data.m_PLYList.size (), 36);

    // 检查首层
    ASSERT_EQ (data.m_PLYList[0].m_GPLYID, 200);
    ASSERT_EQ (data.m_PLYList[0].m_MID, 2100006);
    ASSERT_NEAR (data.m_PLYList[0].m_THICK, 0.125, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[0].m_THETA, -45.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[0].m_SOUT, 1);
    ASSERT_EQ (data.m_PLYList[0].m_GEFLG, -1);

    // 检查最后一层
    ASSERT_EQ (data.m_PLYList[35].m_GPLYID, 239);
    ASSERT_EQ (data.m_PLYList[35].m_MID, 2100006);
    ASSERT_NEAR (data.m_PLYList[35].m_THICK, 0.125, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[35].m_THETA, 45.0, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[35].m_SOUT, 1);

    // 可选：中间层 spot check
    ASSERT_EQ (data.m_PLYList[10].m_GPLYID, 210);
    ASSERT_EQ (data.m_PLYList[10].m_MID, 2100006);
    ASSERT_NEAR (data.m_PLYList[10].m_THICK, 0.125, TOLERANCE);

    ASSERT_EQ (data.m_PLYList[20].m_GPLYID, 220);
    ASSERT_EQ (data.m_PLYList[20].m_MID, 2100006);
    ASSERT_NEAR (data.m_PLYList[20].m_THICK, 0.125, TOLERANCE);

    // 检查所有SOUT
    for (const auto& ply : data.m_PLYList)
        ASSERT_EQ (ply.m_SOUT, 1);
}

// Remark 1: GPLYID唯一；Remark 3: 有GPLYID且主字段有其一即可为有效铺层
TEST_F (PCOMPGParserTest, Remark3)
{
    // 两个铺层，GPLYID唯一，第二层只指定GPLYID和THICK，其余可缺省
    std::vector<std::string> Entry = {
        "PCOMPG   1000   -1.0",
        "        101     200    0.5    0.0    YES",
        "        102                   0.3"  // 只指定GPLYID和THICK
    };
    BDF::divideBulkEntry (Entry, dividedEntryInfo);
    auto status = SG::Import::BDF::BULKDATA::ParsePCOMPG (DB_SERVICEFACTORY, dividedEntryInfo);
    ASSERT_EQ (status, SG::DataStructure::Common::Status::STATUS_Success);

    SG::DataStructure::FEM::PCOMPGData data;
    ASSERT_EQ (DB_SERVICEFACTORY->get<IPCOMPGService> ()->FindById (1000, data), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (data.m_PLYList.size (), 2);
    EXPECT_EQ (data.m_PLYList[0].m_GPLYID, 101);
    EXPECT_EQ (data.m_PLYList[1].m_GPLYID, 102);
}

// Remark 1: 检查GPLYID重复时失败
TEST_F (PCOMPGParserTest, DuplicateGPLYID_Fail)
{
    std::vector<std::string> Entry = {
        "PCOMPG   1001   -1.0",
        "        101     200    0.5    0.0    YES",
        "        101     201    0.5    0.0    YES"  // 重复的GPLYID
    };
    BDF::divideBulkEntry (Entry, dividedEntryInfo);
    auto status = SG::Import::BDF::BULKDATA::ParsePCOMPG (DB_SERVICEFACTORY, dividedEntryInfo);
    ASSERT_EQ (status, SG::DataStructure::Common::Status::STATUS_Failure);
}

// Remark 2: MID/THICK缺省自动继承，首层必须指定
TEST_F (PCOMPGParserTest, Remark2)
{
    // 首层MID、THICK缺省应异常
    std::vector<std::string> Entry1 = {
        "PCOMPG   1002   -1.0",
        "        201"  // 只有GPLYID
    };
    BDF::divideBulkEntry (Entry1, dividedEntryInfo);
    EXPECT_THROW (SG::Import::BDF::BULKDATA::ParsePCOMPG (DB_SERVICEFACTORY, dividedEntryInfo), SG::Utility::ParserError);

    // 单层的 MIDi, Ti, THETAi, SOUTi 四个数必须有一个为非空【否则这个铺层和底部的铺层没有区别】
    std::vector<std::string> Entry2 = {
        "PCOMPG   1003   -1.0",
        //   @1234567@1234567@1234567@1234567@1234567
        "        301     321     0.5     0.0     YES",
        "        302"  // 只指定GPLYID，其余应继承
    };
    BDF::divideBulkEntry (Entry2, dividedEntryInfo);
    EXPECT_THROW (SG::Import::BDF::BULKDATA::ParsePCOMPG (DB_SERVICEFACTORY, dividedEntryInfo), SG::Utility::ParserError);

    // 首层指定MID/THICK，二层缺省自动继承
    std::vector<std::string> Entry3 = {
        "PCOMPG   1004   -1.0",
        //   @1234567@1234567@1234567@1234567@1234567
        "        301     321     0.5     0.0     YES",
        "        302                     5.0"  // 只指定GPLYID，其余应继承
    };
    BDF::divideBulkEntry (Entry3, dividedEntryInfo);
    auto status = SG::Import::BDF::BULKDATA::ParsePCOMPG (DB_SERVICEFACTORY, dividedEntryInfo);

    ASSERT_EQ (status, SG::DataStructure::Common::Status::STATUS_Success);

    SG::DataStructure::FEM::PCOMPGData data;
    ASSERT_EQ (DB_SERVICEFACTORY->get<IPCOMPGService> ()->FindById (1004, data), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (data.m_PLYList[0].m_MID, 321);
    ASSERT_NEAR (data.m_PLYList[0].m_THICK, 0.5, TOLERANCE);
    ASSERT_EQ (data.m_PLYList[1].m_MID, 321);                 // 继承
    ASSERT_NEAR (data.m_PLYList[1].m_THICK, 0.5, TOLERANCE);  // 继承
    ASSERT_NEAR (data.m_PLYList[1].m_THETA, 5.0, TOLERANCE);
}

TEST_F (PCOMPGParserTest, LAM)
{
    std::vector<std::string> Entry = { //$1234567$1234567$1234567$1234567$1234567$1234567$1234567$1234567$1234567
                                       "PCOMPG  1010574                                                 MEM",
                                       "        1       2       0.08    0.      ",
                                       "        2       2       0.08    90.     ",
                                       "        3       2       0.08    45.     ",
                                       "        4       2       0.08    -45.    "
    };
    BDF::divideBulkEntry (Entry, dividedEntryInfo);
    auto status = SG::Import::BDF::BULKDATA::ParsePCOMPG (DB_SERVICEFACTORY, dividedEntryInfo);
    ASSERT_EQ (status, SG::DataStructure::Common::Status::STATUS_Success);

    SG::DataStructure::FEM::PCOMPGData data;
    ASSERT_EQ (DB_SERVICEFACTORY->get<IPCOMPGService> ()->FindById (1010574, data), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (data.m_id, 1010574);
    ASSERT_EQ (std::string (data.m_MICRO), "MEM");
    ASSERT_EQ (data.m_PLYList.size (), 4);

    // 逐层检查
    ASSERT_EQ (data.m_PLYList[0].m_GPLYID, 1);
    ASSERT_EQ (data.m_PLYList[0].m_MID, 2);
    ASSERT_NEAR (data.m_PLYList[0].m_THICK, 0.08, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[0].m_THETA, 0.0, TOLERANCE);

    ASSERT_EQ (data.m_PLYList[1].m_GPLYID, 2);
    ASSERT_EQ (data.m_PLYList[1].m_MID, 2);
    ASSERT_NEAR (data.m_PLYList[1].m_THICK, 0.08, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[1].m_THETA, 90.0, TOLERANCE);

    ASSERT_EQ (data.m_PLYList[2].m_GPLYID, 3);
    ASSERT_EQ (data.m_PLYList[2].m_MID, 2);
    ASSERT_NEAR (data.m_PLYList[2].m_THICK, 0.08, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[2].m_THETA, 45.0, TOLERANCE);

    ASSERT_EQ (data.m_PLYList[3].m_GPLYID, 4);
    ASSERT_EQ (data.m_PLYList[3].m_MID, 2);
    ASSERT_NEAR (data.m_PLYList[3].m_THICK, 0.08, TOLERANCE);
    ASSERT_NEAR (data.m_PLYList[3].m_THETA, -45.0, TOLERANCE);
}